import axios, {
  AxiosHeaderValue,
  AxiosRequestConfig,
  AxiosRequestHeaders,
  ResponseType,
} from 'axios';

import {delToken, getToken} from '@/utils';
import {Toast} from 'native-base';
import {showErrorToast} from './toast';
import {removeItem} from './asyncStorage';
import {navigate} from './routeNavigation';

// create an axios instance
const service = axios.create({
  // baseURL: process.env.NODE_ENV === 'development' ? '' : ('./' + import.meta.env.VITE_APP_NAME), // url = base url + request url
  // withCredentials: true, // send cookies when cross-domain requests
  timeout: 30000, // request timeout
});

// request interceptor
service.interceptors.request.use(
  config => {
    return config;
  },
  error => {
    // do something with request error
    console.log(error); // for debug
    return Promise.reject(error);
  },
);

// response interceptor
service.interceptors.response.use(
  /**
   * If you want to get http information such as headers or status
   * Please return  response => response
   */

  /**
   * Determine the request status by custom code
   * Here is just an example
   * You can also judge the status by HTTP Status Code
   */
  response => {
    const res = response.data;
    if (response.headers['content-type'] === 'text/xml') {
      return response;
    }
    if (
      response.headers['content-type'].includes('application/octet-stream') ||
      response.headers['content-type'].includes('application/vnd.ms-excel')
    ) {
      console.log('responseheaders');
      const content: string = response.headers['content-disposition'];
      const contarr: Array<string> = content.split(';');
      const downloadFileData = {
        fileName: '',
        blob: '',
      };
      contarr.map((item, index) => {
        if (item.indexOf('filename=') > -1) {
          const filename = item.split('=')[1];

          downloadFileData.fileName = decodeURIComponent(filename);
        }
      });
      downloadFileData.blob = response.data;
      response.data = downloadFileData;
      return response;
    }

    // if the custom code is not 20000, it is judged as an error.
    // console.log(res)
    if (res.code !== 0 && res.code !== 3004) {
      Toast.closeAll();

      showErrorToast(res.msg || res.message || '接口调用错误，请联系管理员');

      // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
      if (res.code === 4003) {
        delToken();
      } else if (res.code === 4100) {
        delToken();
        // if (!window.location.href.includes('/login')) {
        goLogin();
        // }
      }
      return Promise.reject(new Error(res.message || 'Error'));
    } else {
      return res;
    }
  },
  error => {
    Toast.closeAll();
    showErrorToast(error.message || error.msg);
    return Promise.reject(error);
  },
);

type RequertConfig = AxiosRequestConfig & {
  option?: {header?: AxiosRequestHeaders};
};

function goLogin() {
  navigate('login');
}

const request = async <T>(
  config: RequertConfig,
): Promise<[Error | null, T | null]> => {
  const token: AxiosHeaderValue = (await getToken()) || '';
  const auth: AxiosRequestHeaders & any = {};
  Object.assign(auth, {
    Authorization: token,
  });
  // debugger
  if (!config.url?.includes('/login')) {
    if (!token) {
      goLogin();
    }
  } else if (!config.url.includes('/getRouter')) {
    Object.assign(auth, {});
  }

  const conf: AxiosRequestConfig = {url: config.url, method: config.method};
  if (conf.method === 'GET' || conf.method === 'get') {
    conf.params = config.data || '';
  } else {
    conf.data = config.data;
  }
  //让 responseType 生效
  if (config.responseType) {
    conf.responseType = config.responseType;
  }
  if (config.option && config.option.header) {
    conf.headers = {
      ...config.option.header,
      ...auth,
    };
  } else if (conf.method === 'POST' || conf.method === 'post') {
    conf.headers = {
      'Content-Type': 'application/json',
      ...auth,
    };
  } else {
    conf.headers = {
      ...auth,
    };
  }
  if (config.timeout !== undefined) {
    conf.timeout = config.timeout;
  }
  return service
    .request(conf)
    .then<[null, T]>(res => [null, res.data])
    .catch<[Error, null]>(err => [err, null]);
};
export default request;
